-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[HLSL] Implement ddx/ddy_fine intrinsics #168874
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
@llvm/pr-subscribers-backend-directx @llvm/pr-subscribers-clang-codegen Author: Alexander Johnston (Alexander-Johnston) ChangesImplements the HLSL ddx_fine and ddy_fine intrinsics. Patch is 39.46 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/168874.diff 25 Files Affected:
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 502382a069856..64de76a01f335 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -5265,6 +5265,18 @@ def HLSLDdyCoarse : LangBuiltin<"HLSL_LANG"> {
let Prototype = "void(...)";
}
+def HLSLDdxFine : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_elementwise_ddx_fine"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def HLSLDdyFine : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_elementwise_ddy_fine"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
// Builtins for XRay.
def XRayCustomEvent : Builtin {
let Spellings = ["__xray_customevent"];
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 12d9a98915ce3..bfa9a53b7804e 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -942,6 +942,24 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
ArrayRef<Value *>{Op0}, nullptr,
"hlsl.ddy.coarse");
}
+ case Builtin::BI__builtin_hlsl_elementwise_ddx_fine: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ if (!E->getArg(0)->getType()->hasFloatingRepresentation())
+ llvm_unreachable("ddx_fine operand must have a float representation");
+ Intrinsic::ID ID = CGM.getHLSLRuntime().getDdxFineIntrinsic();
+ return Builder.CreateIntrinsic(/*ReturnType=*/Op0->getType(), ID,
+ ArrayRef<Value *>{Op0}, nullptr,
+ "hlsl.ddx.fine");
+ }
+ case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ if (!E->getArg(0)->getType()->hasFloatingRepresentation())
+ llvm_unreachable("ddy_fine operand must have a float representation");
+ Intrinsic::ID ID = CGM.getHLSLRuntime().getDdyFineIntrinsic();
+ return Builder.CreateIntrinsic(/*ReturnType=*/Op0->getType(), ID,
+ ArrayRef<Value *>{Op0}, nullptr,
+ "hlsl.ddy.fine");
+ }
case Builtin::BI__builtin_get_spirv_spec_constant_bool:
case Builtin::BI__builtin_get_spirv_spec_constant_short:
case Builtin::BI__builtin_get_spirv_spec_constant_ushort:
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index c883282a8d9c8..2ad39c91280a0 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -171,6 +171,8 @@ class CGHLSLRuntime {
GENERATE_HLSL_INTRINSIC_FUNCTION(GetDimensionsX, resource_getdimensions_x)
GENERATE_HLSL_INTRINSIC_FUNCTION(DdxCoarse, ddx_coarse)
GENERATE_HLSL_INTRINSIC_FUNCTION(DdyCoarse, ddy_coarse)
+ GENERATE_HLSL_INTRINSIC_FUNCTION(DdxFine, ddx_fine)
+ GENERATE_HLSL_INTRINSIC_FUNCTION(DdyFine, ddy_fine)
//===----------------------------------------------------------------------===//
// End of reserved area for HLSL intrinsic getters.
diff --git a/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
index 38b95ee90736a..f58150ed61106 100644
--- a/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
@@ -3014,5 +3014,73 @@ float3 ddy_coarse(float3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_coarse)
float4 ddy_coarse(float4);
+//===----------------------------------------------------------------------===//
+// ddx_fine builtin
+//===----------------------------------------------------------------------===//
+
+/// \fn T ddx_fine(T value)
+/// \brief Computes a high precision partial derivative with respect to the
+/// screen-space x-coordinate.
+/// \param value The input value.
+///
+/// The return value is a floating point scalar or vector containing the high
+/// prevision partial derivative of the input value.
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+half ddx_fine(half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+half2 ddx_fine(half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+half3 ddx_fine(half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+half4 ddx_fine(half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+float ddx_fine(float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+float2 ddx_fine(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+float3 ddx_fine(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+float4 ddx_fine(float4);
+
+//===----------------------------------------------------------------------===//
+// ddy_fine builtin
+//===----------------------------------------------------------------------===//
+
+/// \fn T ddy_fine(T value)
+/// \brief Computes a high precision partial derivative with respect to the
+/// screen-space y-coordinate.
+/// \param value The input value.
+///
+/// The return value is a floating point scalar or vector containing the high
+/// prevision partial derivative of the input value.
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+half ddy_fine(half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+half2 ddy_fine(half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+half3 ddy_fine(half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+half4 ddy_fine(half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+float ddy_fine(float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+float2 ddy_fine(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+float3 ddy_fine(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+float4 ddy_fine(float4);
+
} // namespace hlsl
#endif //_HLSL_HLSL_ALIAS_INTRINSICS_H_
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index c5666941fd36a..cc2939314b0eb 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3211,7 +3211,9 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
case Builtin::BI__builtin_hlsl_elementwise_frac:
case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
- case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse: {
+ case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse:
+ case Builtin::BI__builtin_hlsl_elementwise_ddx_fine:
+ case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
if (SemaRef.checkArgCount(TheCall, 1))
return true;
if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
diff --git a/clang/test/CodeGenHLSL/builtins/ddx-fine-builtin.hlsl b/clang/test/CodeGenHLSL/builtins/ddx-fine-builtin.hlsl
new file mode 100644
index 0000000000000..69f7ab3c6ce62
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddx-fine-builtin.hlsl
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
+
+// CHECK-LABEL: half @_Z17test_f16_ddx_fineDh
+// CHECK: %hlsl.ddx.fine = call {{.*}} half @llvm.dx.ddx.fine.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: half @_Z17test_f16_ddx_fineDh
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} half @llvm.spv.ddx.fine.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddx.fine
+half test_f16_ddx_fine(half val) {
+ return __builtin_hlsl_elementwise_ddx_fine(val);
+}
+
+// CHECK-LABEL: float @_Z17test_f32_ddx_finef
+// CHECK: %hlsl.ddx.fine = call {{.*}} float @llvm.dx.ddx.fine.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: float @_Z17test_f32_ddx_finef
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} float @llvm.spv.ddx.fine.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddx.fine
+float test_f32_ddx_fine(float val) {
+ return __builtin_hlsl_elementwise_ddx_fine(val);
+}
diff --git a/clang/test/CodeGenHLSL/builtins/ddx-fine.hlsl b/clang/test/CodeGenHLSL/builtins/ddx-fine.hlsl
new file mode 100644
index 0000000000000..2630260abcb43
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddx-fine.hlsl
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
+
+// CHECK-LABEL: half @_Z17test_f16_ddx_fineDh
+// CHECK: %hlsl.ddx.fine = call {{.*}} half @llvm.dx.ddx.fine.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: half @_Z17test_f16_ddx_fineDh
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} half @llvm.spv.ddx.fine.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddx.fine
+half test_f16_ddx_fine(half val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <2 x half> @_Z18test_f16_ddx_fine2Dv2_Dh
+// CHECK: %hlsl.ddx.fine = call {{.*}} <2 x half> @llvm.dx.ddx.fine.v2f16(<2 x half> %{{.*}})
+// CHECK: ret <2 x half> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <2 x half> @_Z18test_f16_ddx_fine2Dv2_Dh
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <2 x half> @llvm.spv.ddx.fine.v2f16(<2 x half> %{{.*}})
+// CHECK-SPIRV: ret <2 x half> %hlsl.ddx.fine
+half2 test_f16_ddx_fine2(half2 val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <3 x half> @_Z18test_f16_ddx_fine3Dv3_Dh
+// CHECK: %hlsl.ddx.fine = call {{.*}} <3 x half> @llvm.dx.ddx.fine.v3f16(<3 x half> %{{.*}})
+// CHECK: ret <3 x half> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <3 x half> @_Z18test_f16_ddx_fine3Dv3_Dh
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <3 x half> @llvm.spv.ddx.fine.v3f16(<3 x half> %{{.*}})
+// CHECK-SPIRV: ret <3 x half> %hlsl.ddx.fine
+half3 test_f16_ddx_fine3(half3 val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <4 x half> @_Z18test_f16_ddx_fine4Dv4_Dh
+// CHECK: %hlsl.ddx.fine = call {{.*}} <4 x half> @llvm.dx.ddx.fine.v4f16(<4 x half> %{{.*}})
+// CHECK: ret <4 x half> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <4 x half> @_Z18test_f16_ddx_fine4Dv4_Dh
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <4 x half> @llvm.spv.ddx.fine.v4f16(<4 x half> %{{.*}})
+// CHECK-SPIRV: ret <4 x half> %hlsl.ddx.fine
+half4 test_f16_ddx_fine4(half4 val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: float @_Z17test_f32_ddx_finef
+// CHECK: %hlsl.ddx.fine = call {{.*}} float @llvm.dx.ddx.fine.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: float @_Z17test_f32_ddx_finef
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} float @llvm.spv.ddx.fine.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddx.fine
+float test_f32_ddx_fine(float val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <2 x float> @_Z18test_f32_ddx_fine2Dv2_f
+// CHECK: %hlsl.ddx.fine = call {{.*}} <2 x float> @llvm.dx.ddx.fine.v2f32(<2 x float> %{{.*}})
+// CHECK: ret <2 x float> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <2 x float> @_Z18test_f32_ddx_fine2Dv2_f
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <2 x float> @llvm.spv.ddx.fine.v2f32(<2 x float> %{{.*}})
+// CHECK-SPIRV: ret <2 x float> %hlsl.ddx.fine
+float2 test_f32_ddx_fine2(float2 val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <3 x float> @_Z18test_f32_ddx_fine3Dv3_f
+// CHECK: %hlsl.ddx.fine = call {{.*}} <3 x float> @llvm.dx.ddx.fine.v3f32(<3 x float> %{{.*}})
+// CHECK: ret <3 x float> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <3 x float> @_Z18test_f32_ddx_fine3Dv3_f
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <3 x float> @llvm.spv.ddx.fine.v3f32(<3 x float> %{{.*}})
+// CHECK-SPIRV: ret <3 x float> %hlsl.ddx.fine
+float3 test_f32_ddx_fine3(float3 val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <4 x float> @_Z18test_f32_ddx_fine4Dv4_f
+// CHECK: %hlsl.ddx.fine = call {{.*}} <4 x float> @llvm.dx.ddx.fine.v4f32(<4 x float> %{{.*}})
+// CHECK: ret <4 x float> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <4 x float> @_Z18test_f32_ddx_fine4Dv4_f
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <4 x float> @llvm.spv.ddx.fine.v4f32(<4 x float> %{{.*}})
+// CHECK-SPIRV: ret <4 x float> %hlsl.ddx.fine
+float4 test_f32_ddx_fine4(float4 val) {
+ return ddx_fine(val);
+}
diff --git a/clang/test/CodeGenHLSL/builtins/ddy-fine-builtin.hlsl b/clang/test/CodeGenHLSL/builtins/ddy-fine-builtin.hlsl
new file mode 100644
index 0000000000000..00630721ceb66
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddy-fine-builtin.hlsl
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
+
+// CHECK-LABEL: half @_Z17test_f16_ddy_fineDh
+// CHECK: %hlsl.ddy.fine = call {{.*}} half @llvm.dx.ddy.fine.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: half @_Z17test_f16_ddy_fineDh
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} half @llvm.spv.ddy.fine.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddy.fine
+half test_f16_ddy_fine(half val) {
+ return __builtin_hlsl_elementwise_ddy_fine(val);
+}
+
+// CHECK-LABEL: float @_Z17test_f32_ddy_finef
+// CHECK: %hlsl.ddy.fine = call {{.*}} float @llvm.dx.ddy.fine.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: float @_Z17test_f32_ddy_finef
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} float @llvm.spv.ddy.fine.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddy.fine
+float test_f32_ddy_fine(float val) {
+ return __builtin_hlsl_elementwise_ddy_fine(val);
+}
diff --git a/clang/test/CodeGenHLSL/builtins/ddy-fine.hlsl b/clang/test/CodeGenHLSL/builtins/ddy-fine.hlsl
new file mode 100644
index 0000000000000..7e32ee29e767d
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddy-fine.hlsl
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
+
+// CHECK-LABEL: half @_Z17test_f16_ddy_fineDh
+// CHECK: %hlsl.ddy.fine = call {{.*}} half @llvm.dx.ddy.fine.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: half @_Z17test_f16_ddy_fineDh
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} half @llvm.spv.ddy.fine.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddy.fine
+half test_f16_ddy_fine(half val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <2 x half> @_Z18test_f16_ddy_fine2Dv2_Dh
+// CHECK: %hlsl.ddy.fine = call {{.*}} <2 x half> @llvm.dx.ddy.fine.v2f16(<2 x half> %{{.*}})
+// CHECK: ret <2 x half> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <2 x half> @_Z18test_f16_ddy_fine2Dv2_Dh
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <2 x half> @llvm.spv.ddy.fine.v2f16(<2 x half> %{{.*}})
+// CHECK-SPIRV: ret <2 x half> %hlsl.ddy.fine
+half2 test_f16_ddy_fine2(half2 val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <3 x half> @_Z18test_f16_ddy_fine3Dv3_Dh
+// CHECK: %hlsl.ddy.fine = call {{.*}} <3 x half> @llvm.dx.ddy.fine.v3f16(<3 x half> %{{.*}})
+// CHECK: ret <3 x half> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <3 x half> @_Z18test_f16_ddy_fine3Dv3_Dh
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <3 x half> @llvm.spv.ddy.fine.v3f16(<3 x half> %{{.*}})
+// CHECK-SPIRV: ret <3 x half> %hlsl.ddy.fine
+half3 test_f16_ddy_fine3(half3 val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <4 x half> @_Z18test_f16_ddy_fine4Dv4_Dh
+// CHECK: %hlsl.ddy.fine = call {{.*}} <4 x half> @llvm.dx.ddy.fine.v4f16(<4 x half> %{{.*}})
+// CHECK: ret <4 x half> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <4 x half> @_Z18test_f16_ddy_fine4Dv4_Dh
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <4 x half> @llvm.spv.ddy.fine.v4f16(<4 x half> %{{.*}})
+// CHECK-SPIRV: ret <4 x half> %hlsl.ddy.fine
+half4 test_f16_ddy_fine4(half4 val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: float @_Z17test_f32_ddy_finef
+// CHECK: %hlsl.ddy.fine = call {{.*}} float @llvm.dx.ddy.fine.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: float @_Z17test_f32_ddy_finef
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} float @llvm.spv.ddy.fine.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddy.fine
+float test_f32_ddy_fine(float val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <2 x float> @_Z18test_f32_ddy_fine2Dv2_f
+// CHECK: %hlsl.ddy.fine = call {{.*}} <2 x float> @llvm.dx.ddy.fine.v2f32(<2 x float> %{{.*}})
+// CHECK: ret <2 x float> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <2 x float> @_Z18test_f32_ddy_fine2Dv2_f
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <2 x float> @llvm.spv.ddy.fine.v2f32(<2 x float> %{{.*}})
+// CHECK-SPIRV: ret <2 x float> %hlsl.ddy.fine
+float2 test_f32_ddy_fine2(float2 val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <3 x float> @_Z18test_f32_ddy_fine3Dv3_f
+// CHECK: %hlsl.ddy.fine = call {{.*}} <3 x float> @llvm.dx.ddy.fine.v3f32(<3 x float> %{{.*}})
+// CHECK: ret <3 x float> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <3 x float> @_Z18test_f32_ddy_fine3Dv3_f
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <3 x float> @llvm.spv.ddy.fine.v3f32(<3 x float> %{{.*}})
+// CHECK-SPIRV: ret <3 x float> %hlsl.ddy.fine
+float3 test_f32_ddy_fine3(float3 val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <4 x float> @_Z18test_f32_ddy_fine4Dv4_f
+// CHECK: %hlsl.ddy.fine = call {{.*}} <4 x float> @llvm.dx.ddy.fine.v4f32(<4 x float> %{{.*}})
+// CHECK: ret <4 x float> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <4 x float> @_Z18test_f32_ddy_fine4Dv4_f
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <4 x float> @llvm.spv.ddy.fine.v4f32(<4 x float> %{{.*}})
+// CHECK-SPIRV: ret <4 x float> %hlsl.ddy.fine
+float4 test_f32_ddy_fine4(float4 val) {
+ return ddy_fine(val);
+}
diff --git a/clang/test/SemaHLSL/BuiltIns/ddx-fine-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/ddx-fine-errors.hlsl
new file mode 100644
index 0000000000000..71196943c322a
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/ddx-fine-errors.hlsl
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -verify
+// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-library %s -fnative-half-type -verify
+
+float no_arg() {
+ return __builtin_hlsl_elementwise_ddx_fine();
+ // expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
+}
+
+float too_many_args(float val) {
+ return __builtin_hlsl_elementwise_ddx_fine(val, val);
+ // expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
+}
+
+float test_integer_scalar_input(int val) {
+ return __builtin_hlsl_elementwise_ddx_fine(val);
+ // expected-error@-1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'int')}}
+}
+
+double test_double_scalar_input(double val) {
+ return __builtin_hlsl_elementwise_ddx_fine(val);
+ // expected-error@-1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'double')}}
+}
diff --git a/clang/test/SemaHLSL/BuiltIns/ddy-fine-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/ddy-fine-errors.hlsl
new file mode 100644
index 0000000000000..e17d5f36832b2
--- /dev/null...
[truncated]
|
|
@llvm/pr-subscribers-backend-spir-v Author: Alexander Johnston (Alexander-Johnston) ChangesImplements the HLSL ddx_fine and ddy_fine intrinsics. Patch is 39.46 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/168874.diff 25 Files Affected:
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 502382a069856..64de76a01f335 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -5265,6 +5265,18 @@ def HLSLDdyCoarse : LangBuiltin<"HLSL_LANG"> {
let Prototype = "void(...)";
}
+def HLSLDdxFine : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_elementwise_ddx_fine"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def HLSLDdyFine : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_elementwise_ddy_fine"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
// Builtins for XRay.
def XRayCustomEvent : Builtin {
let Spellings = ["__xray_customevent"];
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 12d9a98915ce3..bfa9a53b7804e 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -942,6 +942,24 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
ArrayRef<Value *>{Op0}, nullptr,
"hlsl.ddy.coarse");
}
+ case Builtin::BI__builtin_hlsl_elementwise_ddx_fine: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ if (!E->getArg(0)->getType()->hasFloatingRepresentation())
+ llvm_unreachable("ddx_fine operand must have a float representation");
+ Intrinsic::ID ID = CGM.getHLSLRuntime().getDdxFineIntrinsic();
+ return Builder.CreateIntrinsic(/*ReturnType=*/Op0->getType(), ID,
+ ArrayRef<Value *>{Op0}, nullptr,
+ "hlsl.ddx.fine");
+ }
+ case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ if (!E->getArg(0)->getType()->hasFloatingRepresentation())
+ llvm_unreachable("ddy_fine operand must have a float representation");
+ Intrinsic::ID ID = CGM.getHLSLRuntime().getDdyFineIntrinsic();
+ return Builder.CreateIntrinsic(/*ReturnType=*/Op0->getType(), ID,
+ ArrayRef<Value *>{Op0}, nullptr,
+ "hlsl.ddy.fine");
+ }
case Builtin::BI__builtin_get_spirv_spec_constant_bool:
case Builtin::BI__builtin_get_spirv_spec_constant_short:
case Builtin::BI__builtin_get_spirv_spec_constant_ushort:
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index c883282a8d9c8..2ad39c91280a0 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -171,6 +171,8 @@ class CGHLSLRuntime {
GENERATE_HLSL_INTRINSIC_FUNCTION(GetDimensionsX, resource_getdimensions_x)
GENERATE_HLSL_INTRINSIC_FUNCTION(DdxCoarse, ddx_coarse)
GENERATE_HLSL_INTRINSIC_FUNCTION(DdyCoarse, ddy_coarse)
+ GENERATE_HLSL_INTRINSIC_FUNCTION(DdxFine, ddx_fine)
+ GENERATE_HLSL_INTRINSIC_FUNCTION(DdyFine, ddy_fine)
//===----------------------------------------------------------------------===//
// End of reserved area for HLSL intrinsic getters.
diff --git a/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
index 38b95ee90736a..f58150ed61106 100644
--- a/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
@@ -3014,5 +3014,73 @@ float3 ddy_coarse(float3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_coarse)
float4 ddy_coarse(float4);
+//===----------------------------------------------------------------------===//
+// ddx_fine builtin
+//===----------------------------------------------------------------------===//
+
+/// \fn T ddx_fine(T value)
+/// \brief Computes a high precision partial derivative with respect to the
+/// screen-space x-coordinate.
+/// \param value The input value.
+///
+/// The return value is a floating point scalar or vector containing the high
+/// prevision partial derivative of the input value.
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+half ddx_fine(half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+half2 ddx_fine(half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+half3 ddx_fine(half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+half4 ddx_fine(half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+float ddx_fine(float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+float2 ddx_fine(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+float3 ddx_fine(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+float4 ddx_fine(float4);
+
+//===----------------------------------------------------------------------===//
+// ddy_fine builtin
+//===----------------------------------------------------------------------===//
+
+/// \fn T ddy_fine(T value)
+/// \brief Computes a high precision partial derivative with respect to the
+/// screen-space y-coordinate.
+/// \param value The input value.
+///
+/// The return value is a floating point scalar or vector containing the high
+/// prevision partial derivative of the input value.
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+half ddy_fine(half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+half2 ddy_fine(half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+half3 ddy_fine(half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+half4 ddy_fine(half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+float ddy_fine(float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+float2 ddy_fine(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+float3 ddy_fine(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+float4 ddy_fine(float4);
+
} // namespace hlsl
#endif //_HLSL_HLSL_ALIAS_INTRINSICS_H_
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index c5666941fd36a..cc2939314b0eb 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3211,7 +3211,9 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
case Builtin::BI__builtin_hlsl_elementwise_frac:
case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
- case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse: {
+ case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse:
+ case Builtin::BI__builtin_hlsl_elementwise_ddx_fine:
+ case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
if (SemaRef.checkArgCount(TheCall, 1))
return true;
if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
diff --git a/clang/test/CodeGenHLSL/builtins/ddx-fine-builtin.hlsl b/clang/test/CodeGenHLSL/builtins/ddx-fine-builtin.hlsl
new file mode 100644
index 0000000000000..69f7ab3c6ce62
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddx-fine-builtin.hlsl
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
+
+// CHECK-LABEL: half @_Z17test_f16_ddx_fineDh
+// CHECK: %hlsl.ddx.fine = call {{.*}} half @llvm.dx.ddx.fine.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: half @_Z17test_f16_ddx_fineDh
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} half @llvm.spv.ddx.fine.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddx.fine
+half test_f16_ddx_fine(half val) {
+ return __builtin_hlsl_elementwise_ddx_fine(val);
+}
+
+// CHECK-LABEL: float @_Z17test_f32_ddx_finef
+// CHECK: %hlsl.ddx.fine = call {{.*}} float @llvm.dx.ddx.fine.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: float @_Z17test_f32_ddx_finef
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} float @llvm.spv.ddx.fine.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddx.fine
+float test_f32_ddx_fine(float val) {
+ return __builtin_hlsl_elementwise_ddx_fine(val);
+}
diff --git a/clang/test/CodeGenHLSL/builtins/ddx-fine.hlsl b/clang/test/CodeGenHLSL/builtins/ddx-fine.hlsl
new file mode 100644
index 0000000000000..2630260abcb43
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddx-fine.hlsl
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
+
+// CHECK-LABEL: half @_Z17test_f16_ddx_fineDh
+// CHECK: %hlsl.ddx.fine = call {{.*}} half @llvm.dx.ddx.fine.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: half @_Z17test_f16_ddx_fineDh
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} half @llvm.spv.ddx.fine.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddx.fine
+half test_f16_ddx_fine(half val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <2 x half> @_Z18test_f16_ddx_fine2Dv2_Dh
+// CHECK: %hlsl.ddx.fine = call {{.*}} <2 x half> @llvm.dx.ddx.fine.v2f16(<2 x half> %{{.*}})
+// CHECK: ret <2 x half> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <2 x half> @_Z18test_f16_ddx_fine2Dv2_Dh
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <2 x half> @llvm.spv.ddx.fine.v2f16(<2 x half> %{{.*}})
+// CHECK-SPIRV: ret <2 x half> %hlsl.ddx.fine
+half2 test_f16_ddx_fine2(half2 val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <3 x half> @_Z18test_f16_ddx_fine3Dv3_Dh
+// CHECK: %hlsl.ddx.fine = call {{.*}} <3 x half> @llvm.dx.ddx.fine.v3f16(<3 x half> %{{.*}})
+// CHECK: ret <3 x half> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <3 x half> @_Z18test_f16_ddx_fine3Dv3_Dh
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <3 x half> @llvm.spv.ddx.fine.v3f16(<3 x half> %{{.*}})
+// CHECK-SPIRV: ret <3 x half> %hlsl.ddx.fine
+half3 test_f16_ddx_fine3(half3 val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <4 x half> @_Z18test_f16_ddx_fine4Dv4_Dh
+// CHECK: %hlsl.ddx.fine = call {{.*}} <4 x half> @llvm.dx.ddx.fine.v4f16(<4 x half> %{{.*}})
+// CHECK: ret <4 x half> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <4 x half> @_Z18test_f16_ddx_fine4Dv4_Dh
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <4 x half> @llvm.spv.ddx.fine.v4f16(<4 x half> %{{.*}})
+// CHECK-SPIRV: ret <4 x half> %hlsl.ddx.fine
+half4 test_f16_ddx_fine4(half4 val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: float @_Z17test_f32_ddx_finef
+// CHECK: %hlsl.ddx.fine = call {{.*}} float @llvm.dx.ddx.fine.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: float @_Z17test_f32_ddx_finef
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} float @llvm.spv.ddx.fine.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddx.fine
+float test_f32_ddx_fine(float val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <2 x float> @_Z18test_f32_ddx_fine2Dv2_f
+// CHECK: %hlsl.ddx.fine = call {{.*}} <2 x float> @llvm.dx.ddx.fine.v2f32(<2 x float> %{{.*}})
+// CHECK: ret <2 x float> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <2 x float> @_Z18test_f32_ddx_fine2Dv2_f
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <2 x float> @llvm.spv.ddx.fine.v2f32(<2 x float> %{{.*}})
+// CHECK-SPIRV: ret <2 x float> %hlsl.ddx.fine
+float2 test_f32_ddx_fine2(float2 val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <3 x float> @_Z18test_f32_ddx_fine3Dv3_f
+// CHECK: %hlsl.ddx.fine = call {{.*}} <3 x float> @llvm.dx.ddx.fine.v3f32(<3 x float> %{{.*}})
+// CHECK: ret <3 x float> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <3 x float> @_Z18test_f32_ddx_fine3Dv3_f
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <3 x float> @llvm.spv.ddx.fine.v3f32(<3 x float> %{{.*}})
+// CHECK-SPIRV: ret <3 x float> %hlsl.ddx.fine
+float3 test_f32_ddx_fine3(float3 val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <4 x float> @_Z18test_f32_ddx_fine4Dv4_f
+// CHECK: %hlsl.ddx.fine = call {{.*}} <4 x float> @llvm.dx.ddx.fine.v4f32(<4 x float> %{{.*}})
+// CHECK: ret <4 x float> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <4 x float> @_Z18test_f32_ddx_fine4Dv4_f
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <4 x float> @llvm.spv.ddx.fine.v4f32(<4 x float> %{{.*}})
+// CHECK-SPIRV: ret <4 x float> %hlsl.ddx.fine
+float4 test_f32_ddx_fine4(float4 val) {
+ return ddx_fine(val);
+}
diff --git a/clang/test/CodeGenHLSL/builtins/ddy-fine-builtin.hlsl b/clang/test/CodeGenHLSL/builtins/ddy-fine-builtin.hlsl
new file mode 100644
index 0000000000000..00630721ceb66
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddy-fine-builtin.hlsl
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
+
+// CHECK-LABEL: half @_Z17test_f16_ddy_fineDh
+// CHECK: %hlsl.ddy.fine = call {{.*}} half @llvm.dx.ddy.fine.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: half @_Z17test_f16_ddy_fineDh
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} half @llvm.spv.ddy.fine.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddy.fine
+half test_f16_ddy_fine(half val) {
+ return __builtin_hlsl_elementwise_ddy_fine(val);
+}
+
+// CHECK-LABEL: float @_Z17test_f32_ddy_finef
+// CHECK: %hlsl.ddy.fine = call {{.*}} float @llvm.dx.ddy.fine.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: float @_Z17test_f32_ddy_finef
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} float @llvm.spv.ddy.fine.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddy.fine
+float test_f32_ddy_fine(float val) {
+ return __builtin_hlsl_elementwise_ddy_fine(val);
+}
diff --git a/clang/test/CodeGenHLSL/builtins/ddy-fine.hlsl b/clang/test/CodeGenHLSL/builtins/ddy-fine.hlsl
new file mode 100644
index 0000000000000..7e32ee29e767d
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddy-fine.hlsl
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
+
+// CHECK-LABEL: half @_Z17test_f16_ddy_fineDh
+// CHECK: %hlsl.ddy.fine = call {{.*}} half @llvm.dx.ddy.fine.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: half @_Z17test_f16_ddy_fineDh
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} half @llvm.spv.ddy.fine.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddy.fine
+half test_f16_ddy_fine(half val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <2 x half> @_Z18test_f16_ddy_fine2Dv2_Dh
+// CHECK: %hlsl.ddy.fine = call {{.*}} <2 x half> @llvm.dx.ddy.fine.v2f16(<2 x half> %{{.*}})
+// CHECK: ret <2 x half> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <2 x half> @_Z18test_f16_ddy_fine2Dv2_Dh
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <2 x half> @llvm.spv.ddy.fine.v2f16(<2 x half> %{{.*}})
+// CHECK-SPIRV: ret <2 x half> %hlsl.ddy.fine
+half2 test_f16_ddy_fine2(half2 val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <3 x half> @_Z18test_f16_ddy_fine3Dv3_Dh
+// CHECK: %hlsl.ddy.fine = call {{.*}} <3 x half> @llvm.dx.ddy.fine.v3f16(<3 x half> %{{.*}})
+// CHECK: ret <3 x half> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <3 x half> @_Z18test_f16_ddy_fine3Dv3_Dh
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <3 x half> @llvm.spv.ddy.fine.v3f16(<3 x half> %{{.*}})
+// CHECK-SPIRV: ret <3 x half> %hlsl.ddy.fine
+half3 test_f16_ddy_fine3(half3 val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <4 x half> @_Z18test_f16_ddy_fine4Dv4_Dh
+// CHECK: %hlsl.ddy.fine = call {{.*}} <4 x half> @llvm.dx.ddy.fine.v4f16(<4 x half> %{{.*}})
+// CHECK: ret <4 x half> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <4 x half> @_Z18test_f16_ddy_fine4Dv4_Dh
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <4 x half> @llvm.spv.ddy.fine.v4f16(<4 x half> %{{.*}})
+// CHECK-SPIRV: ret <4 x half> %hlsl.ddy.fine
+half4 test_f16_ddy_fine4(half4 val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: float @_Z17test_f32_ddy_finef
+// CHECK: %hlsl.ddy.fine = call {{.*}} float @llvm.dx.ddy.fine.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: float @_Z17test_f32_ddy_finef
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} float @llvm.spv.ddy.fine.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddy.fine
+float test_f32_ddy_fine(float val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <2 x float> @_Z18test_f32_ddy_fine2Dv2_f
+// CHECK: %hlsl.ddy.fine = call {{.*}} <2 x float> @llvm.dx.ddy.fine.v2f32(<2 x float> %{{.*}})
+// CHECK: ret <2 x float> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <2 x float> @_Z18test_f32_ddy_fine2Dv2_f
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <2 x float> @llvm.spv.ddy.fine.v2f32(<2 x float> %{{.*}})
+// CHECK-SPIRV: ret <2 x float> %hlsl.ddy.fine
+float2 test_f32_ddy_fine2(float2 val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <3 x float> @_Z18test_f32_ddy_fine3Dv3_f
+// CHECK: %hlsl.ddy.fine = call {{.*}} <3 x float> @llvm.dx.ddy.fine.v3f32(<3 x float> %{{.*}})
+// CHECK: ret <3 x float> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <3 x float> @_Z18test_f32_ddy_fine3Dv3_f
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <3 x float> @llvm.spv.ddy.fine.v3f32(<3 x float> %{{.*}})
+// CHECK-SPIRV: ret <3 x float> %hlsl.ddy.fine
+float3 test_f32_ddy_fine3(float3 val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <4 x float> @_Z18test_f32_ddy_fine4Dv4_f
+// CHECK: %hlsl.ddy.fine = call {{.*}} <4 x float> @llvm.dx.ddy.fine.v4f32(<4 x float> %{{.*}})
+// CHECK: ret <4 x float> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <4 x float> @_Z18test_f32_ddy_fine4Dv4_f
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <4 x float> @llvm.spv.ddy.fine.v4f32(<4 x float> %{{.*}})
+// CHECK-SPIRV: ret <4 x float> %hlsl.ddy.fine
+float4 test_f32_ddy_fine4(float4 val) {
+ return ddy_fine(val);
+}
diff --git a/clang/test/SemaHLSL/BuiltIns/ddx-fine-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/ddx-fine-errors.hlsl
new file mode 100644
index 0000000000000..71196943c322a
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/ddx-fine-errors.hlsl
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -verify
+// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-library %s -fnative-half-type -verify
+
+float no_arg() {
+ return __builtin_hlsl_elementwise_ddx_fine();
+ // expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
+}
+
+float too_many_args(float val) {
+ return __builtin_hlsl_elementwise_ddx_fine(val, val);
+ // expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
+}
+
+float test_integer_scalar_input(int val) {
+ return __builtin_hlsl_elementwise_ddx_fine(val);
+ // expected-error@-1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'int')}}
+}
+
+double test_double_scalar_input(double val) {
+ return __builtin_hlsl_elementwise_ddx_fine(val);
+ // expected-error@-1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'double')}}
+}
diff --git a/clang/test/SemaHLSL/BuiltIns/ddy-fine-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/ddy-fine-errors.hlsl
new file mode 100644
index 0000000000000..e17d5f36832b2
--- /dev/null...
[truncated]
|
|
@llvm/pr-subscribers-backend-x86 Author: Alexander Johnston (Alexander-Johnston) ChangesImplements the HLSL ddx_fine and ddy_fine intrinsics. Patch is 39.46 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/168874.diff 25 Files Affected:
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 502382a069856..64de76a01f335 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -5265,6 +5265,18 @@ def HLSLDdyCoarse : LangBuiltin<"HLSL_LANG"> {
let Prototype = "void(...)";
}
+def HLSLDdxFine : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_elementwise_ddx_fine"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def HLSLDdyFine : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_elementwise_ddy_fine"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
// Builtins for XRay.
def XRayCustomEvent : Builtin {
let Spellings = ["__xray_customevent"];
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 12d9a98915ce3..bfa9a53b7804e 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -942,6 +942,24 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
ArrayRef<Value *>{Op0}, nullptr,
"hlsl.ddy.coarse");
}
+ case Builtin::BI__builtin_hlsl_elementwise_ddx_fine: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ if (!E->getArg(0)->getType()->hasFloatingRepresentation())
+ llvm_unreachable("ddx_fine operand must have a float representation");
+ Intrinsic::ID ID = CGM.getHLSLRuntime().getDdxFineIntrinsic();
+ return Builder.CreateIntrinsic(/*ReturnType=*/Op0->getType(), ID,
+ ArrayRef<Value *>{Op0}, nullptr,
+ "hlsl.ddx.fine");
+ }
+ case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ if (!E->getArg(0)->getType()->hasFloatingRepresentation())
+ llvm_unreachable("ddy_fine operand must have a float representation");
+ Intrinsic::ID ID = CGM.getHLSLRuntime().getDdyFineIntrinsic();
+ return Builder.CreateIntrinsic(/*ReturnType=*/Op0->getType(), ID,
+ ArrayRef<Value *>{Op0}, nullptr,
+ "hlsl.ddy.fine");
+ }
case Builtin::BI__builtin_get_spirv_spec_constant_bool:
case Builtin::BI__builtin_get_spirv_spec_constant_short:
case Builtin::BI__builtin_get_spirv_spec_constant_ushort:
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index c883282a8d9c8..2ad39c91280a0 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -171,6 +171,8 @@ class CGHLSLRuntime {
GENERATE_HLSL_INTRINSIC_FUNCTION(GetDimensionsX, resource_getdimensions_x)
GENERATE_HLSL_INTRINSIC_FUNCTION(DdxCoarse, ddx_coarse)
GENERATE_HLSL_INTRINSIC_FUNCTION(DdyCoarse, ddy_coarse)
+ GENERATE_HLSL_INTRINSIC_FUNCTION(DdxFine, ddx_fine)
+ GENERATE_HLSL_INTRINSIC_FUNCTION(DdyFine, ddy_fine)
//===----------------------------------------------------------------------===//
// End of reserved area for HLSL intrinsic getters.
diff --git a/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
index 38b95ee90736a..f58150ed61106 100644
--- a/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
@@ -3014,5 +3014,73 @@ float3 ddy_coarse(float3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_coarse)
float4 ddy_coarse(float4);
+//===----------------------------------------------------------------------===//
+// ddx_fine builtin
+//===----------------------------------------------------------------------===//
+
+/// \fn T ddx_fine(T value)
+/// \brief Computes a high precision partial derivative with respect to the
+/// screen-space x-coordinate.
+/// \param value The input value.
+///
+/// The return value is a floating point scalar or vector containing the high
+/// prevision partial derivative of the input value.
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+half ddx_fine(half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+half2 ddx_fine(half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+half3 ddx_fine(half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+half4 ddx_fine(half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+float ddx_fine(float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+float2 ddx_fine(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+float3 ddx_fine(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+float4 ddx_fine(float4);
+
+//===----------------------------------------------------------------------===//
+// ddy_fine builtin
+//===----------------------------------------------------------------------===//
+
+/// \fn T ddy_fine(T value)
+/// \brief Computes a high precision partial derivative with respect to the
+/// screen-space y-coordinate.
+/// \param value The input value.
+///
+/// The return value is a floating point scalar or vector containing the high
+/// prevision partial derivative of the input value.
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+half ddy_fine(half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+half2 ddy_fine(half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+half3 ddy_fine(half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+half4 ddy_fine(half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+float ddy_fine(float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+float2 ddy_fine(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+float3 ddy_fine(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+float4 ddy_fine(float4);
+
} // namespace hlsl
#endif //_HLSL_HLSL_ALIAS_INTRINSICS_H_
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index c5666941fd36a..cc2939314b0eb 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3211,7 +3211,9 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
case Builtin::BI__builtin_hlsl_elementwise_frac:
case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
- case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse: {
+ case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse:
+ case Builtin::BI__builtin_hlsl_elementwise_ddx_fine:
+ case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
if (SemaRef.checkArgCount(TheCall, 1))
return true;
if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
diff --git a/clang/test/CodeGenHLSL/builtins/ddx-fine-builtin.hlsl b/clang/test/CodeGenHLSL/builtins/ddx-fine-builtin.hlsl
new file mode 100644
index 0000000000000..69f7ab3c6ce62
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddx-fine-builtin.hlsl
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
+
+// CHECK-LABEL: half @_Z17test_f16_ddx_fineDh
+// CHECK: %hlsl.ddx.fine = call {{.*}} half @llvm.dx.ddx.fine.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: half @_Z17test_f16_ddx_fineDh
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} half @llvm.spv.ddx.fine.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddx.fine
+half test_f16_ddx_fine(half val) {
+ return __builtin_hlsl_elementwise_ddx_fine(val);
+}
+
+// CHECK-LABEL: float @_Z17test_f32_ddx_finef
+// CHECK: %hlsl.ddx.fine = call {{.*}} float @llvm.dx.ddx.fine.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: float @_Z17test_f32_ddx_finef
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} float @llvm.spv.ddx.fine.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddx.fine
+float test_f32_ddx_fine(float val) {
+ return __builtin_hlsl_elementwise_ddx_fine(val);
+}
diff --git a/clang/test/CodeGenHLSL/builtins/ddx-fine.hlsl b/clang/test/CodeGenHLSL/builtins/ddx-fine.hlsl
new file mode 100644
index 0000000000000..2630260abcb43
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddx-fine.hlsl
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
+
+// CHECK-LABEL: half @_Z17test_f16_ddx_fineDh
+// CHECK: %hlsl.ddx.fine = call {{.*}} half @llvm.dx.ddx.fine.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: half @_Z17test_f16_ddx_fineDh
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} half @llvm.spv.ddx.fine.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddx.fine
+half test_f16_ddx_fine(half val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <2 x half> @_Z18test_f16_ddx_fine2Dv2_Dh
+// CHECK: %hlsl.ddx.fine = call {{.*}} <2 x half> @llvm.dx.ddx.fine.v2f16(<2 x half> %{{.*}})
+// CHECK: ret <2 x half> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <2 x half> @_Z18test_f16_ddx_fine2Dv2_Dh
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <2 x half> @llvm.spv.ddx.fine.v2f16(<2 x half> %{{.*}})
+// CHECK-SPIRV: ret <2 x half> %hlsl.ddx.fine
+half2 test_f16_ddx_fine2(half2 val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <3 x half> @_Z18test_f16_ddx_fine3Dv3_Dh
+// CHECK: %hlsl.ddx.fine = call {{.*}} <3 x half> @llvm.dx.ddx.fine.v3f16(<3 x half> %{{.*}})
+// CHECK: ret <3 x half> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <3 x half> @_Z18test_f16_ddx_fine3Dv3_Dh
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <3 x half> @llvm.spv.ddx.fine.v3f16(<3 x half> %{{.*}})
+// CHECK-SPIRV: ret <3 x half> %hlsl.ddx.fine
+half3 test_f16_ddx_fine3(half3 val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <4 x half> @_Z18test_f16_ddx_fine4Dv4_Dh
+// CHECK: %hlsl.ddx.fine = call {{.*}} <4 x half> @llvm.dx.ddx.fine.v4f16(<4 x half> %{{.*}})
+// CHECK: ret <4 x half> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <4 x half> @_Z18test_f16_ddx_fine4Dv4_Dh
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <4 x half> @llvm.spv.ddx.fine.v4f16(<4 x half> %{{.*}})
+// CHECK-SPIRV: ret <4 x half> %hlsl.ddx.fine
+half4 test_f16_ddx_fine4(half4 val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: float @_Z17test_f32_ddx_finef
+// CHECK: %hlsl.ddx.fine = call {{.*}} float @llvm.dx.ddx.fine.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: float @_Z17test_f32_ddx_finef
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} float @llvm.spv.ddx.fine.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddx.fine
+float test_f32_ddx_fine(float val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <2 x float> @_Z18test_f32_ddx_fine2Dv2_f
+// CHECK: %hlsl.ddx.fine = call {{.*}} <2 x float> @llvm.dx.ddx.fine.v2f32(<2 x float> %{{.*}})
+// CHECK: ret <2 x float> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <2 x float> @_Z18test_f32_ddx_fine2Dv2_f
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <2 x float> @llvm.spv.ddx.fine.v2f32(<2 x float> %{{.*}})
+// CHECK-SPIRV: ret <2 x float> %hlsl.ddx.fine
+float2 test_f32_ddx_fine2(float2 val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <3 x float> @_Z18test_f32_ddx_fine3Dv3_f
+// CHECK: %hlsl.ddx.fine = call {{.*}} <3 x float> @llvm.dx.ddx.fine.v3f32(<3 x float> %{{.*}})
+// CHECK: ret <3 x float> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <3 x float> @_Z18test_f32_ddx_fine3Dv3_f
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <3 x float> @llvm.spv.ddx.fine.v3f32(<3 x float> %{{.*}})
+// CHECK-SPIRV: ret <3 x float> %hlsl.ddx.fine
+float3 test_f32_ddx_fine3(float3 val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <4 x float> @_Z18test_f32_ddx_fine4Dv4_f
+// CHECK: %hlsl.ddx.fine = call {{.*}} <4 x float> @llvm.dx.ddx.fine.v4f32(<4 x float> %{{.*}})
+// CHECK: ret <4 x float> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <4 x float> @_Z18test_f32_ddx_fine4Dv4_f
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <4 x float> @llvm.spv.ddx.fine.v4f32(<4 x float> %{{.*}})
+// CHECK-SPIRV: ret <4 x float> %hlsl.ddx.fine
+float4 test_f32_ddx_fine4(float4 val) {
+ return ddx_fine(val);
+}
diff --git a/clang/test/CodeGenHLSL/builtins/ddy-fine-builtin.hlsl b/clang/test/CodeGenHLSL/builtins/ddy-fine-builtin.hlsl
new file mode 100644
index 0000000000000..00630721ceb66
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddy-fine-builtin.hlsl
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
+
+// CHECK-LABEL: half @_Z17test_f16_ddy_fineDh
+// CHECK: %hlsl.ddy.fine = call {{.*}} half @llvm.dx.ddy.fine.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: half @_Z17test_f16_ddy_fineDh
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} half @llvm.spv.ddy.fine.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddy.fine
+half test_f16_ddy_fine(half val) {
+ return __builtin_hlsl_elementwise_ddy_fine(val);
+}
+
+// CHECK-LABEL: float @_Z17test_f32_ddy_finef
+// CHECK: %hlsl.ddy.fine = call {{.*}} float @llvm.dx.ddy.fine.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: float @_Z17test_f32_ddy_finef
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} float @llvm.spv.ddy.fine.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddy.fine
+float test_f32_ddy_fine(float val) {
+ return __builtin_hlsl_elementwise_ddy_fine(val);
+}
diff --git a/clang/test/CodeGenHLSL/builtins/ddy-fine.hlsl b/clang/test/CodeGenHLSL/builtins/ddy-fine.hlsl
new file mode 100644
index 0000000000000..7e32ee29e767d
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddy-fine.hlsl
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
+
+// CHECK-LABEL: half @_Z17test_f16_ddy_fineDh
+// CHECK: %hlsl.ddy.fine = call {{.*}} half @llvm.dx.ddy.fine.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: half @_Z17test_f16_ddy_fineDh
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} half @llvm.spv.ddy.fine.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddy.fine
+half test_f16_ddy_fine(half val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <2 x half> @_Z18test_f16_ddy_fine2Dv2_Dh
+// CHECK: %hlsl.ddy.fine = call {{.*}} <2 x half> @llvm.dx.ddy.fine.v2f16(<2 x half> %{{.*}})
+// CHECK: ret <2 x half> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <2 x half> @_Z18test_f16_ddy_fine2Dv2_Dh
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <2 x half> @llvm.spv.ddy.fine.v2f16(<2 x half> %{{.*}})
+// CHECK-SPIRV: ret <2 x half> %hlsl.ddy.fine
+half2 test_f16_ddy_fine2(half2 val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <3 x half> @_Z18test_f16_ddy_fine3Dv3_Dh
+// CHECK: %hlsl.ddy.fine = call {{.*}} <3 x half> @llvm.dx.ddy.fine.v3f16(<3 x half> %{{.*}})
+// CHECK: ret <3 x half> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <3 x half> @_Z18test_f16_ddy_fine3Dv3_Dh
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <3 x half> @llvm.spv.ddy.fine.v3f16(<3 x half> %{{.*}})
+// CHECK-SPIRV: ret <3 x half> %hlsl.ddy.fine
+half3 test_f16_ddy_fine3(half3 val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <4 x half> @_Z18test_f16_ddy_fine4Dv4_Dh
+// CHECK: %hlsl.ddy.fine = call {{.*}} <4 x half> @llvm.dx.ddy.fine.v4f16(<4 x half> %{{.*}})
+// CHECK: ret <4 x half> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <4 x half> @_Z18test_f16_ddy_fine4Dv4_Dh
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <4 x half> @llvm.spv.ddy.fine.v4f16(<4 x half> %{{.*}})
+// CHECK-SPIRV: ret <4 x half> %hlsl.ddy.fine
+half4 test_f16_ddy_fine4(half4 val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: float @_Z17test_f32_ddy_finef
+// CHECK: %hlsl.ddy.fine = call {{.*}} float @llvm.dx.ddy.fine.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: float @_Z17test_f32_ddy_finef
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} float @llvm.spv.ddy.fine.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddy.fine
+float test_f32_ddy_fine(float val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <2 x float> @_Z18test_f32_ddy_fine2Dv2_f
+// CHECK: %hlsl.ddy.fine = call {{.*}} <2 x float> @llvm.dx.ddy.fine.v2f32(<2 x float> %{{.*}})
+// CHECK: ret <2 x float> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <2 x float> @_Z18test_f32_ddy_fine2Dv2_f
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <2 x float> @llvm.spv.ddy.fine.v2f32(<2 x float> %{{.*}})
+// CHECK-SPIRV: ret <2 x float> %hlsl.ddy.fine
+float2 test_f32_ddy_fine2(float2 val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <3 x float> @_Z18test_f32_ddy_fine3Dv3_f
+// CHECK: %hlsl.ddy.fine = call {{.*}} <3 x float> @llvm.dx.ddy.fine.v3f32(<3 x float> %{{.*}})
+// CHECK: ret <3 x float> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <3 x float> @_Z18test_f32_ddy_fine3Dv3_f
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <3 x float> @llvm.spv.ddy.fine.v3f32(<3 x float> %{{.*}})
+// CHECK-SPIRV: ret <3 x float> %hlsl.ddy.fine
+float3 test_f32_ddy_fine3(float3 val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <4 x float> @_Z18test_f32_ddy_fine4Dv4_f
+// CHECK: %hlsl.ddy.fine = call {{.*}} <4 x float> @llvm.dx.ddy.fine.v4f32(<4 x float> %{{.*}})
+// CHECK: ret <4 x float> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <4 x float> @_Z18test_f32_ddy_fine4Dv4_f
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <4 x float> @llvm.spv.ddy.fine.v4f32(<4 x float> %{{.*}})
+// CHECK-SPIRV: ret <4 x float> %hlsl.ddy.fine
+float4 test_f32_ddy_fine4(float4 val) {
+ return ddy_fine(val);
+}
diff --git a/clang/test/SemaHLSL/BuiltIns/ddx-fine-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/ddx-fine-errors.hlsl
new file mode 100644
index 0000000000000..71196943c322a
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/ddx-fine-errors.hlsl
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -verify
+// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-library %s -fnative-half-type -verify
+
+float no_arg() {
+ return __builtin_hlsl_elementwise_ddx_fine();
+ // expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
+}
+
+float too_many_args(float val) {
+ return __builtin_hlsl_elementwise_ddx_fine(val, val);
+ // expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
+}
+
+float test_integer_scalar_input(int val) {
+ return __builtin_hlsl_elementwise_ddx_fine(val);
+ // expected-error@-1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'int')}}
+}
+
+double test_double_scalar_input(double val) {
+ return __builtin_hlsl_elementwise_ddx_fine(val);
+ // expected-error@-1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'double')}}
+}
diff --git a/clang/test/SemaHLSL/BuiltIns/ddy-fine-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/ddy-fine-errors.hlsl
new file mode 100644
index 0000000000000..e17d5f36832b2
--- /dev/null...
[truncated]
|
|
@llvm/pr-subscribers-llvm-ir Author: Alexander Johnston (Alexander-Johnston) ChangesImplements the HLSL ddx_fine and ddy_fine intrinsics. Patch is 39.46 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/168874.diff 25 Files Affected:
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 502382a069856..64de76a01f335 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -5265,6 +5265,18 @@ def HLSLDdyCoarse : LangBuiltin<"HLSL_LANG"> {
let Prototype = "void(...)";
}
+def HLSLDdxFine : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_elementwise_ddx_fine"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def HLSLDdyFine : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_elementwise_ddy_fine"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
// Builtins for XRay.
def XRayCustomEvent : Builtin {
let Spellings = ["__xray_customevent"];
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 12d9a98915ce3..bfa9a53b7804e 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -942,6 +942,24 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
ArrayRef<Value *>{Op0}, nullptr,
"hlsl.ddy.coarse");
}
+ case Builtin::BI__builtin_hlsl_elementwise_ddx_fine: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ if (!E->getArg(0)->getType()->hasFloatingRepresentation())
+ llvm_unreachable("ddx_fine operand must have a float representation");
+ Intrinsic::ID ID = CGM.getHLSLRuntime().getDdxFineIntrinsic();
+ return Builder.CreateIntrinsic(/*ReturnType=*/Op0->getType(), ID,
+ ArrayRef<Value *>{Op0}, nullptr,
+ "hlsl.ddx.fine");
+ }
+ case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ if (!E->getArg(0)->getType()->hasFloatingRepresentation())
+ llvm_unreachable("ddy_fine operand must have a float representation");
+ Intrinsic::ID ID = CGM.getHLSLRuntime().getDdyFineIntrinsic();
+ return Builder.CreateIntrinsic(/*ReturnType=*/Op0->getType(), ID,
+ ArrayRef<Value *>{Op0}, nullptr,
+ "hlsl.ddy.fine");
+ }
case Builtin::BI__builtin_get_spirv_spec_constant_bool:
case Builtin::BI__builtin_get_spirv_spec_constant_short:
case Builtin::BI__builtin_get_spirv_spec_constant_ushort:
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index c883282a8d9c8..2ad39c91280a0 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -171,6 +171,8 @@ class CGHLSLRuntime {
GENERATE_HLSL_INTRINSIC_FUNCTION(GetDimensionsX, resource_getdimensions_x)
GENERATE_HLSL_INTRINSIC_FUNCTION(DdxCoarse, ddx_coarse)
GENERATE_HLSL_INTRINSIC_FUNCTION(DdyCoarse, ddy_coarse)
+ GENERATE_HLSL_INTRINSIC_FUNCTION(DdxFine, ddx_fine)
+ GENERATE_HLSL_INTRINSIC_FUNCTION(DdyFine, ddy_fine)
//===----------------------------------------------------------------------===//
// End of reserved area for HLSL intrinsic getters.
diff --git a/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
index 38b95ee90736a..f58150ed61106 100644
--- a/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
@@ -3014,5 +3014,73 @@ float3 ddy_coarse(float3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_coarse)
float4 ddy_coarse(float4);
+//===----------------------------------------------------------------------===//
+// ddx_fine builtin
+//===----------------------------------------------------------------------===//
+
+/// \fn T ddx_fine(T value)
+/// \brief Computes a high precision partial derivative with respect to the
+/// screen-space x-coordinate.
+/// \param value The input value.
+///
+/// The return value is a floating point scalar or vector containing the high
+/// prevision partial derivative of the input value.
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+half ddx_fine(half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+half2 ddx_fine(half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+half3 ddx_fine(half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+half4 ddx_fine(half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+float ddx_fine(float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+float2 ddx_fine(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+float3 ddx_fine(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+float4 ddx_fine(float4);
+
+//===----------------------------------------------------------------------===//
+// ddy_fine builtin
+//===----------------------------------------------------------------------===//
+
+/// \fn T ddy_fine(T value)
+/// \brief Computes a high precision partial derivative with respect to the
+/// screen-space y-coordinate.
+/// \param value The input value.
+///
+/// The return value is a floating point scalar or vector containing the high
+/// prevision partial derivative of the input value.
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+half ddy_fine(half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+half2 ddy_fine(half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+half3 ddy_fine(half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+half4 ddy_fine(half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+float ddy_fine(float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+float2 ddy_fine(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+float3 ddy_fine(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+float4 ddy_fine(float4);
+
} // namespace hlsl
#endif //_HLSL_HLSL_ALIAS_INTRINSICS_H_
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index c5666941fd36a..cc2939314b0eb 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3211,7 +3211,9 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
case Builtin::BI__builtin_hlsl_elementwise_frac:
case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
- case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse: {
+ case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse:
+ case Builtin::BI__builtin_hlsl_elementwise_ddx_fine:
+ case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
if (SemaRef.checkArgCount(TheCall, 1))
return true;
if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
diff --git a/clang/test/CodeGenHLSL/builtins/ddx-fine-builtin.hlsl b/clang/test/CodeGenHLSL/builtins/ddx-fine-builtin.hlsl
new file mode 100644
index 0000000000000..69f7ab3c6ce62
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddx-fine-builtin.hlsl
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
+
+// CHECK-LABEL: half @_Z17test_f16_ddx_fineDh
+// CHECK: %hlsl.ddx.fine = call {{.*}} half @llvm.dx.ddx.fine.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: half @_Z17test_f16_ddx_fineDh
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} half @llvm.spv.ddx.fine.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddx.fine
+half test_f16_ddx_fine(half val) {
+ return __builtin_hlsl_elementwise_ddx_fine(val);
+}
+
+// CHECK-LABEL: float @_Z17test_f32_ddx_finef
+// CHECK: %hlsl.ddx.fine = call {{.*}} float @llvm.dx.ddx.fine.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: float @_Z17test_f32_ddx_finef
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} float @llvm.spv.ddx.fine.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddx.fine
+float test_f32_ddx_fine(float val) {
+ return __builtin_hlsl_elementwise_ddx_fine(val);
+}
diff --git a/clang/test/CodeGenHLSL/builtins/ddx-fine.hlsl b/clang/test/CodeGenHLSL/builtins/ddx-fine.hlsl
new file mode 100644
index 0000000000000..2630260abcb43
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddx-fine.hlsl
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
+
+// CHECK-LABEL: half @_Z17test_f16_ddx_fineDh
+// CHECK: %hlsl.ddx.fine = call {{.*}} half @llvm.dx.ddx.fine.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: half @_Z17test_f16_ddx_fineDh
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} half @llvm.spv.ddx.fine.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddx.fine
+half test_f16_ddx_fine(half val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <2 x half> @_Z18test_f16_ddx_fine2Dv2_Dh
+// CHECK: %hlsl.ddx.fine = call {{.*}} <2 x half> @llvm.dx.ddx.fine.v2f16(<2 x half> %{{.*}})
+// CHECK: ret <2 x half> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <2 x half> @_Z18test_f16_ddx_fine2Dv2_Dh
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <2 x half> @llvm.spv.ddx.fine.v2f16(<2 x half> %{{.*}})
+// CHECK-SPIRV: ret <2 x half> %hlsl.ddx.fine
+half2 test_f16_ddx_fine2(half2 val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <3 x half> @_Z18test_f16_ddx_fine3Dv3_Dh
+// CHECK: %hlsl.ddx.fine = call {{.*}} <3 x half> @llvm.dx.ddx.fine.v3f16(<3 x half> %{{.*}})
+// CHECK: ret <3 x half> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <3 x half> @_Z18test_f16_ddx_fine3Dv3_Dh
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <3 x half> @llvm.spv.ddx.fine.v3f16(<3 x half> %{{.*}})
+// CHECK-SPIRV: ret <3 x half> %hlsl.ddx.fine
+half3 test_f16_ddx_fine3(half3 val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <4 x half> @_Z18test_f16_ddx_fine4Dv4_Dh
+// CHECK: %hlsl.ddx.fine = call {{.*}} <4 x half> @llvm.dx.ddx.fine.v4f16(<4 x half> %{{.*}})
+// CHECK: ret <4 x half> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <4 x half> @_Z18test_f16_ddx_fine4Dv4_Dh
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <4 x half> @llvm.spv.ddx.fine.v4f16(<4 x half> %{{.*}})
+// CHECK-SPIRV: ret <4 x half> %hlsl.ddx.fine
+half4 test_f16_ddx_fine4(half4 val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: float @_Z17test_f32_ddx_finef
+// CHECK: %hlsl.ddx.fine = call {{.*}} float @llvm.dx.ddx.fine.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: float @_Z17test_f32_ddx_finef
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} float @llvm.spv.ddx.fine.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddx.fine
+float test_f32_ddx_fine(float val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <2 x float> @_Z18test_f32_ddx_fine2Dv2_f
+// CHECK: %hlsl.ddx.fine = call {{.*}} <2 x float> @llvm.dx.ddx.fine.v2f32(<2 x float> %{{.*}})
+// CHECK: ret <2 x float> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <2 x float> @_Z18test_f32_ddx_fine2Dv2_f
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <2 x float> @llvm.spv.ddx.fine.v2f32(<2 x float> %{{.*}})
+// CHECK-SPIRV: ret <2 x float> %hlsl.ddx.fine
+float2 test_f32_ddx_fine2(float2 val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <3 x float> @_Z18test_f32_ddx_fine3Dv3_f
+// CHECK: %hlsl.ddx.fine = call {{.*}} <3 x float> @llvm.dx.ddx.fine.v3f32(<3 x float> %{{.*}})
+// CHECK: ret <3 x float> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <3 x float> @_Z18test_f32_ddx_fine3Dv3_f
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <3 x float> @llvm.spv.ddx.fine.v3f32(<3 x float> %{{.*}})
+// CHECK-SPIRV: ret <3 x float> %hlsl.ddx.fine
+float3 test_f32_ddx_fine3(float3 val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <4 x float> @_Z18test_f32_ddx_fine4Dv4_f
+// CHECK: %hlsl.ddx.fine = call {{.*}} <4 x float> @llvm.dx.ddx.fine.v4f32(<4 x float> %{{.*}})
+// CHECK: ret <4 x float> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <4 x float> @_Z18test_f32_ddx_fine4Dv4_f
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <4 x float> @llvm.spv.ddx.fine.v4f32(<4 x float> %{{.*}})
+// CHECK-SPIRV: ret <4 x float> %hlsl.ddx.fine
+float4 test_f32_ddx_fine4(float4 val) {
+ return ddx_fine(val);
+}
diff --git a/clang/test/CodeGenHLSL/builtins/ddy-fine-builtin.hlsl b/clang/test/CodeGenHLSL/builtins/ddy-fine-builtin.hlsl
new file mode 100644
index 0000000000000..00630721ceb66
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddy-fine-builtin.hlsl
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
+
+// CHECK-LABEL: half @_Z17test_f16_ddy_fineDh
+// CHECK: %hlsl.ddy.fine = call {{.*}} half @llvm.dx.ddy.fine.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: half @_Z17test_f16_ddy_fineDh
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} half @llvm.spv.ddy.fine.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddy.fine
+half test_f16_ddy_fine(half val) {
+ return __builtin_hlsl_elementwise_ddy_fine(val);
+}
+
+// CHECK-LABEL: float @_Z17test_f32_ddy_finef
+// CHECK: %hlsl.ddy.fine = call {{.*}} float @llvm.dx.ddy.fine.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: float @_Z17test_f32_ddy_finef
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} float @llvm.spv.ddy.fine.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddy.fine
+float test_f32_ddy_fine(float val) {
+ return __builtin_hlsl_elementwise_ddy_fine(val);
+}
diff --git a/clang/test/CodeGenHLSL/builtins/ddy-fine.hlsl b/clang/test/CodeGenHLSL/builtins/ddy-fine.hlsl
new file mode 100644
index 0000000000000..7e32ee29e767d
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddy-fine.hlsl
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
+
+// CHECK-LABEL: half @_Z17test_f16_ddy_fineDh
+// CHECK: %hlsl.ddy.fine = call {{.*}} half @llvm.dx.ddy.fine.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: half @_Z17test_f16_ddy_fineDh
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} half @llvm.spv.ddy.fine.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddy.fine
+half test_f16_ddy_fine(half val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <2 x half> @_Z18test_f16_ddy_fine2Dv2_Dh
+// CHECK: %hlsl.ddy.fine = call {{.*}} <2 x half> @llvm.dx.ddy.fine.v2f16(<2 x half> %{{.*}})
+// CHECK: ret <2 x half> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <2 x half> @_Z18test_f16_ddy_fine2Dv2_Dh
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <2 x half> @llvm.spv.ddy.fine.v2f16(<2 x half> %{{.*}})
+// CHECK-SPIRV: ret <2 x half> %hlsl.ddy.fine
+half2 test_f16_ddy_fine2(half2 val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <3 x half> @_Z18test_f16_ddy_fine3Dv3_Dh
+// CHECK: %hlsl.ddy.fine = call {{.*}} <3 x half> @llvm.dx.ddy.fine.v3f16(<3 x half> %{{.*}})
+// CHECK: ret <3 x half> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <3 x half> @_Z18test_f16_ddy_fine3Dv3_Dh
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <3 x half> @llvm.spv.ddy.fine.v3f16(<3 x half> %{{.*}})
+// CHECK-SPIRV: ret <3 x half> %hlsl.ddy.fine
+half3 test_f16_ddy_fine3(half3 val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <4 x half> @_Z18test_f16_ddy_fine4Dv4_Dh
+// CHECK: %hlsl.ddy.fine = call {{.*}} <4 x half> @llvm.dx.ddy.fine.v4f16(<4 x half> %{{.*}})
+// CHECK: ret <4 x half> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <4 x half> @_Z18test_f16_ddy_fine4Dv4_Dh
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <4 x half> @llvm.spv.ddy.fine.v4f16(<4 x half> %{{.*}})
+// CHECK-SPIRV: ret <4 x half> %hlsl.ddy.fine
+half4 test_f16_ddy_fine4(half4 val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: float @_Z17test_f32_ddy_finef
+// CHECK: %hlsl.ddy.fine = call {{.*}} float @llvm.dx.ddy.fine.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: float @_Z17test_f32_ddy_finef
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} float @llvm.spv.ddy.fine.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddy.fine
+float test_f32_ddy_fine(float val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <2 x float> @_Z18test_f32_ddy_fine2Dv2_f
+// CHECK: %hlsl.ddy.fine = call {{.*}} <2 x float> @llvm.dx.ddy.fine.v2f32(<2 x float> %{{.*}})
+// CHECK: ret <2 x float> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <2 x float> @_Z18test_f32_ddy_fine2Dv2_f
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <2 x float> @llvm.spv.ddy.fine.v2f32(<2 x float> %{{.*}})
+// CHECK-SPIRV: ret <2 x float> %hlsl.ddy.fine
+float2 test_f32_ddy_fine2(float2 val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <3 x float> @_Z18test_f32_ddy_fine3Dv3_f
+// CHECK: %hlsl.ddy.fine = call {{.*}} <3 x float> @llvm.dx.ddy.fine.v3f32(<3 x float> %{{.*}})
+// CHECK: ret <3 x float> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <3 x float> @_Z18test_f32_ddy_fine3Dv3_f
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <3 x float> @llvm.spv.ddy.fine.v3f32(<3 x float> %{{.*}})
+// CHECK-SPIRV: ret <3 x float> %hlsl.ddy.fine
+float3 test_f32_ddy_fine3(float3 val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <4 x float> @_Z18test_f32_ddy_fine4Dv4_f
+// CHECK: %hlsl.ddy.fine = call {{.*}} <4 x float> @llvm.dx.ddy.fine.v4f32(<4 x float> %{{.*}})
+// CHECK: ret <4 x float> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <4 x float> @_Z18test_f32_ddy_fine4Dv4_f
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <4 x float> @llvm.spv.ddy.fine.v4f32(<4 x float> %{{.*}})
+// CHECK-SPIRV: ret <4 x float> %hlsl.ddy.fine
+float4 test_f32_ddy_fine4(float4 val) {
+ return ddy_fine(val);
+}
diff --git a/clang/test/SemaHLSL/BuiltIns/ddx-fine-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/ddx-fine-errors.hlsl
new file mode 100644
index 0000000000000..71196943c322a
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/ddx-fine-errors.hlsl
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -verify
+// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-library %s -fnative-half-type -verify
+
+float no_arg() {
+ return __builtin_hlsl_elementwise_ddx_fine();
+ // expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
+}
+
+float too_many_args(float val) {
+ return __builtin_hlsl_elementwise_ddx_fine(val, val);
+ // expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
+}
+
+float test_integer_scalar_input(int val) {
+ return __builtin_hlsl_elementwise_ddx_fine(val);
+ // expected-error@-1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'int')}}
+}
+
+double test_double_scalar_input(double val) {
+ return __builtin_hlsl_elementwise_ddx_fine(val);
+ // expected-error@-1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'double')}}
+}
diff --git a/clang/test/SemaHLSL/BuiltIns/ddy-fine-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/ddy-fine-errors.hlsl
new file mode 100644
index 0000000000000..e17d5f36832b2
--- /dev/null...
[truncated]
|
|
@llvm/pr-subscribers-hlsl Author: Alexander Johnston (Alexander-Johnston) ChangesImplements the HLSL ddx_fine and ddy_fine intrinsics. Patch is 39.46 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/168874.diff 25 Files Affected:
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 502382a069856..64de76a01f335 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -5265,6 +5265,18 @@ def HLSLDdyCoarse : LangBuiltin<"HLSL_LANG"> {
let Prototype = "void(...)";
}
+def HLSLDdxFine : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_elementwise_ddx_fine"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def HLSLDdyFine : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_elementwise_ddy_fine"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
// Builtins for XRay.
def XRayCustomEvent : Builtin {
let Spellings = ["__xray_customevent"];
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 12d9a98915ce3..bfa9a53b7804e 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -942,6 +942,24 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
ArrayRef<Value *>{Op0}, nullptr,
"hlsl.ddy.coarse");
}
+ case Builtin::BI__builtin_hlsl_elementwise_ddx_fine: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ if (!E->getArg(0)->getType()->hasFloatingRepresentation())
+ llvm_unreachable("ddx_fine operand must have a float representation");
+ Intrinsic::ID ID = CGM.getHLSLRuntime().getDdxFineIntrinsic();
+ return Builder.CreateIntrinsic(/*ReturnType=*/Op0->getType(), ID,
+ ArrayRef<Value *>{Op0}, nullptr,
+ "hlsl.ddx.fine");
+ }
+ case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ if (!E->getArg(0)->getType()->hasFloatingRepresentation())
+ llvm_unreachable("ddy_fine operand must have a float representation");
+ Intrinsic::ID ID = CGM.getHLSLRuntime().getDdyFineIntrinsic();
+ return Builder.CreateIntrinsic(/*ReturnType=*/Op0->getType(), ID,
+ ArrayRef<Value *>{Op0}, nullptr,
+ "hlsl.ddy.fine");
+ }
case Builtin::BI__builtin_get_spirv_spec_constant_bool:
case Builtin::BI__builtin_get_spirv_spec_constant_short:
case Builtin::BI__builtin_get_spirv_spec_constant_ushort:
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index c883282a8d9c8..2ad39c91280a0 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -171,6 +171,8 @@ class CGHLSLRuntime {
GENERATE_HLSL_INTRINSIC_FUNCTION(GetDimensionsX, resource_getdimensions_x)
GENERATE_HLSL_INTRINSIC_FUNCTION(DdxCoarse, ddx_coarse)
GENERATE_HLSL_INTRINSIC_FUNCTION(DdyCoarse, ddy_coarse)
+ GENERATE_HLSL_INTRINSIC_FUNCTION(DdxFine, ddx_fine)
+ GENERATE_HLSL_INTRINSIC_FUNCTION(DdyFine, ddy_fine)
//===----------------------------------------------------------------------===//
// End of reserved area for HLSL intrinsic getters.
diff --git a/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
index 38b95ee90736a..f58150ed61106 100644
--- a/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h
@@ -3014,5 +3014,73 @@ float3 ddy_coarse(float3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_coarse)
float4 ddy_coarse(float4);
+//===----------------------------------------------------------------------===//
+// ddx_fine builtin
+//===----------------------------------------------------------------------===//
+
+/// \fn T ddx_fine(T value)
+/// \brief Computes a high precision partial derivative with respect to the
+/// screen-space x-coordinate.
+/// \param value The input value.
+///
+/// The return value is a floating point scalar or vector containing the high
+/// prevision partial derivative of the input value.
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+half ddx_fine(half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+half2 ddx_fine(half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+half3 ddx_fine(half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+half4 ddx_fine(half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+float ddx_fine(float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+float2 ddx_fine(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+float3 ddx_fine(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddx_fine)
+float4 ddx_fine(float4);
+
+//===----------------------------------------------------------------------===//
+// ddy_fine builtin
+//===----------------------------------------------------------------------===//
+
+/// \fn T ddy_fine(T value)
+/// \brief Computes a high precision partial derivative with respect to the
+/// screen-space y-coordinate.
+/// \param value The input value.
+///
+/// The return value is a floating point scalar or vector containing the high
+/// prevision partial derivative of the input value.
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+half ddy_fine(half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+half2 ddy_fine(half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+half3 ddy_fine(half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+half4 ddy_fine(half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+float ddy_fine(float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+float2 ddy_fine(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+float3 ddy_fine(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_ddy_fine)
+float4 ddy_fine(float4);
+
} // namespace hlsl
#endif //_HLSL_HLSL_ALIAS_INTRINSICS_H_
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index c5666941fd36a..cc2939314b0eb 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -3211,7 +3211,9 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
case Builtin::BI__builtin_hlsl_elementwise_frac:
case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse:
- case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse: {
+ case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse:
+ case Builtin::BI__builtin_hlsl_elementwise_ddx_fine:
+ case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {
if (SemaRef.checkArgCount(TheCall, 1))
return true;
if (CheckAllArgTypesAreCorrect(&SemaRef, TheCall,
diff --git a/clang/test/CodeGenHLSL/builtins/ddx-fine-builtin.hlsl b/clang/test/CodeGenHLSL/builtins/ddx-fine-builtin.hlsl
new file mode 100644
index 0000000000000..69f7ab3c6ce62
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddx-fine-builtin.hlsl
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
+
+// CHECK-LABEL: half @_Z17test_f16_ddx_fineDh
+// CHECK: %hlsl.ddx.fine = call {{.*}} half @llvm.dx.ddx.fine.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: half @_Z17test_f16_ddx_fineDh
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} half @llvm.spv.ddx.fine.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddx.fine
+half test_f16_ddx_fine(half val) {
+ return __builtin_hlsl_elementwise_ddx_fine(val);
+}
+
+// CHECK-LABEL: float @_Z17test_f32_ddx_finef
+// CHECK: %hlsl.ddx.fine = call {{.*}} float @llvm.dx.ddx.fine.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: float @_Z17test_f32_ddx_finef
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} float @llvm.spv.ddx.fine.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddx.fine
+float test_f32_ddx_fine(float val) {
+ return __builtin_hlsl_elementwise_ddx_fine(val);
+}
diff --git a/clang/test/CodeGenHLSL/builtins/ddx-fine.hlsl b/clang/test/CodeGenHLSL/builtins/ddx-fine.hlsl
new file mode 100644
index 0000000000000..2630260abcb43
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddx-fine.hlsl
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
+
+// CHECK-LABEL: half @_Z17test_f16_ddx_fineDh
+// CHECK: %hlsl.ddx.fine = call {{.*}} half @llvm.dx.ddx.fine.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: half @_Z17test_f16_ddx_fineDh
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} half @llvm.spv.ddx.fine.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddx.fine
+half test_f16_ddx_fine(half val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <2 x half> @_Z18test_f16_ddx_fine2Dv2_Dh
+// CHECK: %hlsl.ddx.fine = call {{.*}} <2 x half> @llvm.dx.ddx.fine.v2f16(<2 x half> %{{.*}})
+// CHECK: ret <2 x half> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <2 x half> @_Z18test_f16_ddx_fine2Dv2_Dh
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <2 x half> @llvm.spv.ddx.fine.v2f16(<2 x half> %{{.*}})
+// CHECK-SPIRV: ret <2 x half> %hlsl.ddx.fine
+half2 test_f16_ddx_fine2(half2 val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <3 x half> @_Z18test_f16_ddx_fine3Dv3_Dh
+// CHECK: %hlsl.ddx.fine = call {{.*}} <3 x half> @llvm.dx.ddx.fine.v3f16(<3 x half> %{{.*}})
+// CHECK: ret <3 x half> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <3 x half> @_Z18test_f16_ddx_fine3Dv3_Dh
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <3 x half> @llvm.spv.ddx.fine.v3f16(<3 x half> %{{.*}})
+// CHECK-SPIRV: ret <3 x half> %hlsl.ddx.fine
+half3 test_f16_ddx_fine3(half3 val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <4 x half> @_Z18test_f16_ddx_fine4Dv4_Dh
+// CHECK: %hlsl.ddx.fine = call {{.*}} <4 x half> @llvm.dx.ddx.fine.v4f16(<4 x half> %{{.*}})
+// CHECK: ret <4 x half> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <4 x half> @_Z18test_f16_ddx_fine4Dv4_Dh
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <4 x half> @llvm.spv.ddx.fine.v4f16(<4 x half> %{{.*}})
+// CHECK-SPIRV: ret <4 x half> %hlsl.ddx.fine
+half4 test_f16_ddx_fine4(half4 val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: float @_Z17test_f32_ddx_finef
+// CHECK: %hlsl.ddx.fine = call {{.*}} float @llvm.dx.ddx.fine.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: float @_Z17test_f32_ddx_finef
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} float @llvm.spv.ddx.fine.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddx.fine
+float test_f32_ddx_fine(float val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <2 x float> @_Z18test_f32_ddx_fine2Dv2_f
+// CHECK: %hlsl.ddx.fine = call {{.*}} <2 x float> @llvm.dx.ddx.fine.v2f32(<2 x float> %{{.*}})
+// CHECK: ret <2 x float> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <2 x float> @_Z18test_f32_ddx_fine2Dv2_f
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <2 x float> @llvm.spv.ddx.fine.v2f32(<2 x float> %{{.*}})
+// CHECK-SPIRV: ret <2 x float> %hlsl.ddx.fine
+float2 test_f32_ddx_fine2(float2 val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <3 x float> @_Z18test_f32_ddx_fine3Dv3_f
+// CHECK: %hlsl.ddx.fine = call {{.*}} <3 x float> @llvm.dx.ddx.fine.v3f32(<3 x float> %{{.*}})
+// CHECK: ret <3 x float> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <3 x float> @_Z18test_f32_ddx_fine3Dv3_f
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <3 x float> @llvm.spv.ddx.fine.v3f32(<3 x float> %{{.*}})
+// CHECK-SPIRV: ret <3 x float> %hlsl.ddx.fine
+float3 test_f32_ddx_fine3(float3 val) {
+ return ddx_fine(val);
+}
+
+// CHECK-LABEL: <4 x float> @_Z18test_f32_ddx_fine4Dv4_f
+// CHECK: %hlsl.ddx.fine = call {{.*}} <4 x float> @llvm.dx.ddx.fine.v4f32(<4 x float> %{{.*}})
+// CHECK: ret <4 x float> %hlsl.ddx.fine
+// CHECK-LABEL-SPIRV: <4 x float> @_Z18test_f32_ddx_fine4Dv4_f
+// CHECK-SPIRV: %hlsl.ddx.fine = call {{.*}} <4 x float> @llvm.spv.ddx.fine.v4f32(<4 x float> %{{.*}})
+// CHECK-SPIRV: ret <4 x float> %hlsl.ddx.fine
+float4 test_f32_ddx_fine4(float4 val) {
+ return ddx_fine(val);
+}
diff --git a/clang/test/CodeGenHLSL/builtins/ddy-fine-builtin.hlsl b/clang/test/CodeGenHLSL/builtins/ddy-fine-builtin.hlsl
new file mode 100644
index 0000000000000..00630721ceb66
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddy-fine-builtin.hlsl
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
+
+// CHECK-LABEL: half @_Z17test_f16_ddy_fineDh
+// CHECK: %hlsl.ddy.fine = call {{.*}} half @llvm.dx.ddy.fine.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: half @_Z17test_f16_ddy_fineDh
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} half @llvm.spv.ddy.fine.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddy.fine
+half test_f16_ddy_fine(half val) {
+ return __builtin_hlsl_elementwise_ddy_fine(val);
+}
+
+// CHECK-LABEL: float @_Z17test_f32_ddy_finef
+// CHECK: %hlsl.ddy.fine = call {{.*}} float @llvm.dx.ddy.fine.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: float @_Z17test_f32_ddy_finef
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} float @llvm.spv.ddy.fine.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddy.fine
+float test_f32_ddy_fine(float val) {
+ return __builtin_hlsl_elementwise_ddy_fine(val);
+}
diff --git a/clang/test/CodeGenHLSL/builtins/ddy-fine.hlsl b/clang/test/CodeGenHLSL/builtins/ddy-fine.hlsl
new file mode 100644
index 0000000000000..7e32ee29e767d
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/ddy-fine.hlsl
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-pc-vulkan-compute %s \
+// RUN: -emit-llvm -disable-llvm-passes -fnative-half-type -o - | \
+// RUN: FileCheck %s --check-prefixes=CHECK-SPIRV
+
+// CHECK-LABEL: half @_Z17test_f16_ddy_fineDh
+// CHECK: %hlsl.ddy.fine = call {{.*}} half @llvm.dx.ddy.fine.f16(half %{{.*}})
+// CHECK: ret half %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: half @_Z17test_f16_ddy_fineDh
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} half @llvm.spv.ddy.fine.f16(half %{{.*}})
+// CHECK-SPIRV: ret half %hlsl.ddy.fine
+half test_f16_ddy_fine(half val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <2 x half> @_Z18test_f16_ddy_fine2Dv2_Dh
+// CHECK: %hlsl.ddy.fine = call {{.*}} <2 x half> @llvm.dx.ddy.fine.v2f16(<2 x half> %{{.*}})
+// CHECK: ret <2 x half> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <2 x half> @_Z18test_f16_ddy_fine2Dv2_Dh
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <2 x half> @llvm.spv.ddy.fine.v2f16(<2 x half> %{{.*}})
+// CHECK-SPIRV: ret <2 x half> %hlsl.ddy.fine
+half2 test_f16_ddy_fine2(half2 val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <3 x half> @_Z18test_f16_ddy_fine3Dv3_Dh
+// CHECK: %hlsl.ddy.fine = call {{.*}} <3 x half> @llvm.dx.ddy.fine.v3f16(<3 x half> %{{.*}})
+// CHECK: ret <3 x half> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <3 x half> @_Z18test_f16_ddy_fine3Dv3_Dh
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <3 x half> @llvm.spv.ddy.fine.v3f16(<3 x half> %{{.*}})
+// CHECK-SPIRV: ret <3 x half> %hlsl.ddy.fine
+half3 test_f16_ddy_fine3(half3 val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <4 x half> @_Z18test_f16_ddy_fine4Dv4_Dh
+// CHECK: %hlsl.ddy.fine = call {{.*}} <4 x half> @llvm.dx.ddy.fine.v4f16(<4 x half> %{{.*}})
+// CHECK: ret <4 x half> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <4 x half> @_Z18test_f16_ddy_fine4Dv4_Dh
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <4 x half> @llvm.spv.ddy.fine.v4f16(<4 x half> %{{.*}})
+// CHECK-SPIRV: ret <4 x half> %hlsl.ddy.fine
+half4 test_f16_ddy_fine4(half4 val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: float @_Z17test_f32_ddy_finef
+// CHECK: %hlsl.ddy.fine = call {{.*}} float @llvm.dx.ddy.fine.f32(float %{{.*}})
+// CHECK: ret float %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: float @_Z17test_f32_ddy_finef
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} float @llvm.spv.ddy.fine.f32(float %{{.*}})
+// CHECK-SPIRV: ret float %hlsl.ddy.fine
+float test_f32_ddy_fine(float val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <2 x float> @_Z18test_f32_ddy_fine2Dv2_f
+// CHECK: %hlsl.ddy.fine = call {{.*}} <2 x float> @llvm.dx.ddy.fine.v2f32(<2 x float> %{{.*}})
+// CHECK: ret <2 x float> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <2 x float> @_Z18test_f32_ddy_fine2Dv2_f
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <2 x float> @llvm.spv.ddy.fine.v2f32(<2 x float> %{{.*}})
+// CHECK-SPIRV: ret <2 x float> %hlsl.ddy.fine
+float2 test_f32_ddy_fine2(float2 val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <3 x float> @_Z18test_f32_ddy_fine3Dv3_f
+// CHECK: %hlsl.ddy.fine = call {{.*}} <3 x float> @llvm.dx.ddy.fine.v3f32(<3 x float> %{{.*}})
+// CHECK: ret <3 x float> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <3 x float> @_Z18test_f32_ddy_fine3Dv3_f
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <3 x float> @llvm.spv.ddy.fine.v3f32(<3 x float> %{{.*}})
+// CHECK-SPIRV: ret <3 x float> %hlsl.ddy.fine
+float3 test_f32_ddy_fine3(float3 val) {
+ return ddy_fine(val);
+}
+
+// CHECK-LABEL: <4 x float> @_Z18test_f32_ddy_fine4Dv4_f
+// CHECK: %hlsl.ddy.fine = call {{.*}} <4 x float> @llvm.dx.ddy.fine.v4f32(<4 x float> %{{.*}})
+// CHECK: ret <4 x float> %hlsl.ddy.fine
+// CHECK-LABEL-SPIRV: <4 x float> @_Z18test_f32_ddy_fine4Dv4_f
+// CHECK-SPIRV: %hlsl.ddy.fine = call {{.*}} <4 x float> @llvm.spv.ddy.fine.v4f32(<4 x float> %{{.*}})
+// CHECK-SPIRV: ret <4 x float> %hlsl.ddy.fine
+float4 test_f32_ddy_fine4(float4 val) {
+ return ddy_fine(val);
+}
diff --git a/clang/test/SemaHLSL/BuiltIns/ddx-fine-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/ddx-fine-errors.hlsl
new file mode 100644
index 0000000000000..71196943c322a
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/ddx-fine-errors.hlsl
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -verify
+// RUN: %clang_cc1 -triple spirv-unknown-vulkan1.3-library %s -fnative-half-type -verify
+
+float no_arg() {
+ return __builtin_hlsl_elementwise_ddx_fine();
+ // expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
+}
+
+float too_many_args(float val) {
+ return __builtin_hlsl_elementwise_ddx_fine(val, val);
+ // expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
+}
+
+float test_integer_scalar_input(int val) {
+ return __builtin_hlsl_elementwise_ddx_fine(val);
+ // expected-error@-1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'int')}}
+}
+
+double test_double_scalar_input(double val) {
+ return __builtin_hlsl_elementwise_ddx_fine(val);
+ // expected-error@-1 {{1st argument must be a scalar or vector of 16 or 32 bit floating-point types (was 'double')}}
+}
diff --git a/clang/test/SemaHLSL/BuiltIns/ddy-fine-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/ddy-fine-errors.hlsl
new file mode 100644
index 0000000000000..e17d5f36832b2
--- /dev/null...
[truncated]
|
🐧 Linux x64 Test Results
|
Implements the HLSL ddx_fine and ddy_fine intrinsics together as the implementations are nearly identical.
420c196 to
7d46602
Compare
Implements the HLSL ddx_fine and ddy_fine intrinsics.
For the SPIRV backend the intrinsics are ensured to be unavailable in opencl (as they require fragment execution stage).
Closes #99098
Closes #99101